﻿using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Text;
using SqlSugar;
using System.Threading.Tasks;
using System.Linq;
using AutoMapper;
using FastMvc.Crud.Models;
using FastMvc.Repositories;
using FastMvc.Exceptions;
using FastMvc.Models;
using FastMvc.Auth;

namespace FastMvc.Crud
{
    /// <summary>
    /// 自定义封装Crud方法的Controller
    /// </summary>
    public class CrudController<TEntity, TEntityDto, TPrimaryKey, TListPageRequestDto, TCreateDto, TUpdateDto> : BaseController 
        where TEntity: DBEntity<TPrimaryKey>, new()
        where TEntityDto: DtoEntity<TPrimaryKey>
        where TListPageRequestDto: ListPageRequestDto ,new() 
    {
        private ICrudService<TEntity, TEntityDto, TPrimaryKey, TListPageRequestDto, TCreateDto, TUpdateDto> crudService;

        public CrudController(ICrudService<TEntity, TEntityDto, TPrimaryKey, TListPageRequestDto, TCreateDto, TUpdateDto> crudService)
        {
            this.crudService = crudService;
        }

        /// <summary>
        /// 列表查询
        /// </summary>
        [HttpGet("")]
        public virtual async Task<BaseResult<ListData<TEntityDto>>> QueryList([FromQuery]TListPageRequestDto listPageRequest)
        {
            var result = await this.crudService.QueryList(listPageRequest);

            return await SetResultNotNull(result);
        }

        /// <summary>
        /// 详情查询
        /// </summary>
        [HttpGet("{sId}")]
        public virtual async Task<BaseResult<TEntityDto>> QueryDetail(TPrimaryKey sId)
        {
            var result = await crudService.QueryDetail(sId);
            return await SetResultNotNull(result);
        }

        /// <summary>
        /// 新建
        /// </summary>
        [HttpPost("")]
        public virtual async Task<BaseResult<TEntityDto>> CreateNew([FromBody] TCreateDto createDto)
        {
            CheckCreatePermission();

            var result = await crudService.CreateNew(createDto);
            return await SetResultNotNull(result);
        }

        /// <summary>
        /// 修改
        /// </summary>
        [HttpPut("{sId}")]
        public virtual async Task<BaseResult<TEntityDto>> Update(TPrimaryKey sId, [FromBody] TUpdateDto updateDto)
        {
            CheckUpdatePermission(); // 检查当前资源的更新权限

            var result = await crudService.Update(sId, updateDto);
            return await SetResultNotNull(result);
        }

        /// <summary>
        /// 删除
        /// </summary>
        [HttpDelete("{sId}")]
        public virtual async Task<BaseResult<TEntityDto>> Delete(TPrimaryKey sId)
        {
            CheckDeletePermission();

            var result = await this.crudService.Delete(sId);
            return await SetResultNotNull(result);
        }

        #region 权限

        /// <summary>
        /// 检查有没有当前数据的Create权限
        /// </summary>
        protected void CheckCreatePermission()
        {
            var cPermission = GetControllerPermission();
            if (cPermission != null && cPermission.CrudCreate)
            {
                var permission = cPermission.pName + ".create";
                CheckPermission(permission);
            }
        }

        /// <summary>
        /// 检查有没有当前数据的Update权限
        /// </summary>
        protected void CheckUpdatePermission()
        {
            var cPermission = GetControllerPermission();
            if (cPermission != null && cPermission.CrudUpdate)
            {
                var permission = cPermission.pName + ".update";
                CheckPermission(permission);
            }
        }

        /// <summary>
        /// 检查有没有当前数据的Delete权限
        /// </summary>
        protected void CheckDeletePermission()
        {
            var cPermission = GetControllerPermission();
            if (cPermission != null && cPermission.CrudDelete)
            {
                var permission = cPermission.Permission + ".delete";
                CheckPermission(permission);
            }
        }

        private PermissionCheckAttribute GetControllerPermission()
        {
            var ats = this.GetType().GetCustomAttributes(typeof(PermissionCheckAttribute), false);
            if (ats.Length > 0)
            {
                return ats[0] as PermissionCheckAttribute;
            }

            return null;
        }
        #endregion
    }

    public class CrudController<TEntity, TEntityDto, TPrimaryKey, TListPageRequestDto> : CrudController<TEntity, TEntityDto, TPrimaryKey, TListPageRequestDto, TEntityDto, TEntityDto>
        where TEntity : DBEntity<TPrimaryKey>, new()
        where TEntityDto : DtoEntity<TPrimaryKey>
        where TListPageRequestDto: ListPageRequestDto, new()
    {
        public CrudController(ICrudService<TEntity, TEntityDto, TPrimaryKey, TListPageRequestDto> crudService)
            : base(crudService)
        { }
    }

    public class CrudController<TEntity, TEntityDto, TPrimaryKey> : CrudController<TEntity, TEntityDto, TPrimaryKey, ListPageRequestDto>
        where TEntity : DBEntity<TPrimaryKey>, new()
        where TEntityDto : DtoEntity<TPrimaryKey>
    {
        public CrudController(ICrudService<TEntity, TEntityDto, TPrimaryKey> crudService)
            : base(crudService)
        { }
    }

    public class CrudController<TEntity, TEntityDto> : CrudController<TEntity, TEntityDto, Guid, ListPageRequestDto>
        where TEntity : DBEntity<Guid>, new()
        where TEntityDto : DtoEntity<Guid>
    {
        public CrudController(ICrudService<TEntity, TEntityDto> crudService)
            : base(crudService)
        { }
    }
}
